#include <assert.h>

#include "utils.h"

uint32_t usnet::ReverseBits(uint32_t num)
{
    constexpr uint32_t first_bit_mask { 1u };
    uint32_t ret { 0 };
    for (int k = 32; k != 0; --k) {
        uint32_t bit = (num & first_bit_mask);
        num >>= 1;
        ret <<= 1;
        ret |= bit;
    }
    return ret;
}

uint64_t usnet::ReverseBits(uint64_t num)
{
    constexpr uint64_t first_bit_mask { 1u };
    uint64_t ret { 0 };
    for (int k = 32; k != 0; --k) {
        uint64_t bit = (num & first_bit_mask);
        num >>= 1;
        ret <<= 1;
        ret |= bit;
    }
    return ret;
}

std::string usnet::StringTrimHead(const std::string& str)
{
    int k = 0;
    const int len = str.length();
    for (; k < len; ++k) {
        if ((str[k] != ' ') && (str[k] != '\t')) {
            break;
        }
    }
    return str.substr(k, len - k);
}

std::string usnet::StringTrimTail(const std::string& str)
{
    int k = str.length();
    if (str.back() == '\n') {
        --k;
    }
    for(; k != 0; --k) {
        if ((str[k - 1] != ' ') && (str[k - 1] != '\t')) {
            break;
        }
    }
    return str.substr(0, k);
}

std::vector<std::string> usnet::StringSplit(std::string str, const std::string& delimiter)
{
    std::vector<std::string> result;
    str = StringTrim(str);
    int left { 0 };
    int right { 0 };
    const int strlen = str.length();
    const int delimlen = delimiter.length();
    while (right < strlen) {
        right = str.find(delimiter, left);
        if (right == std::string::npos) {
            right = strlen;
        }
        result.push_back(str.substr(left, right - left));
        left = right + delimlen;
    }
    return result;
}

void usnet::EthAddr2Num(uint8_t* ethaddr, const char* str)
{
    auto slice_list = usnet::StringSplit(std::string(str), ":");
    assert(slice_list.size() == 6);
    for (int k = 0; k < slice_list.size(); ++k) {
        ethaddr[k] = std::stoul(slice_list[k].c_str(), nullptr, 16);
    }
}

int usnet::ByteCompare(const uint8_t* array1, const uint8_t* array2, const std::size_t len)
{
    for (int k = len; k != 0; --k) {
        if (array1[k - 1] != array2[k -1]) {
            return -1;
        }
    }
    return 0;
}